<template>
  <!-- <div class="layer-container"> -->
  <div
    :id="`entity-${entityData.id}`"
    class="entity-container resize-drag"
    :class="{
      'up-panel': entityData.id === selectEntityPanel && focusBox === 'entity',
    }"
    :style="containerStyle()"
    @click.stop="UpEntityPanel(entityData.id)"
  >
    <div class="header" @dblclick="resetInitWidth()">
      <div class="panel-name" :title="entityData.name">
        {{ entityData.name }}
      </div>
      <div class="func-list">
        <div v-if="!isNotAllowed" class="func-icon">
          <a-tooltip placement="top">
            <template slot="title">
              <span>添加抽屉</span>
            </template>
            <div @click="addAttr">
              <a-icon-font type="iconjiahao1" />
            </div>
          </a-tooltip>
        </div>
        <div v-if="!isNotAllowed" class="func-icon">
          <a-tooltip placement="top">
            <template slot="title">
              <span>重置</span>
            </template>
            <div @click="entityReset">
              <a-icon-font type="icona-qingxi-caozuojilubeifen3" />
            </div>
          </a-tooltip>
        </div>
        <div class="func-icon" @click.stop="closeEntity">
          <a-icon-font type="iconicon-beifen1" />
        </div>
      </div>
    </div>

    <div class="layer-body">
      <draggable
        :list="entityData.items"
        :disabled="isNotAllowed || !enabled"
        class="list-group"
        v-bind="dragOptions"
        handle=".drag-btn"
        @start="enabled = true"
        @end="dragEnd"
      >
        <transition-group
          type="transition"
          :name="!enabled ? 'flip-list' : null"
        >
          <div
            v-for="(item, index) in entityData.items"
            :key="`item-${index}`"
            class="layer-item"
            @drop.prevent.stop
          >
            <div
              v-if="
                !(isNotAllowed && (!item.visible || item.children.length === 0))
              "
            >
              <div class="item-header" :class="{ unvisible: !item.visible }">
                <div
                  v-if="editName !== item.name"
                  class="item-title"
                  @dblclick.stop="editItemName(item)"
                >
                  {{ item.name }}
                </div>
                <!-- 编辑状态 -->
                <div v-else class="tabs-label-edit">
                  <a-input
                    v-model="activeEditItemName"
                    v-focus
                    type="text"
                    size="small"
                    style="width: 100%;"
                    @pressEnter="($event) => $event.target.blur()"
                    @blur="($event) => editLayerNameCheck($event, item)"
                  />
                </div>

                <div class="item-func">
                  <!-- eyes -->
                  <div
                    v-if="!isNotAllowed"
                    class="layer-eyes icon-style"
                    @click.stop="itemToggleShow(item._id_)"
                    @mouseenter="mouseenter()"
                    @mouseleave="mouseleave()"
                  >
                    <a-icon-font
                      :type="
                        item.visible
                          ? hovering
                            ? 'icona-chakanbeifen21'
                            : 'icona-chakanbeifen2'
                          : hovering
                          ? 'icona-chakanbeifen19'
                          : 'icona-chakanbeifen14'
                      "
                    />
                  </div>
                  <!-- 折叠 -->
                  <div
                    class="folding-state icon-style"
                    @click.stop="toggleFold(item._id_)"
                  >
                    <a-icon-font
                      :type="
                        expandedKeys.includes(item._id_)
                          ? 'iconicon-beifen'
                          : 'iconicon-beifen-right'
                      "
                    />
                  </div>

                  <div v-if="!isNotAllowed" class="icon-style divider"></div>

                  <div v-if="!isNotAllowed" class="icon-style drag-btn">
                    <a-icon-font type="icontuodong" />
                  </div>
                </div>
              </div>
              <div :class="{ 'close-fold': !expandedKeys.includes(item._id_) }">
                <draggable
                  class="item-content"
                  :list="item.children"
                  :disabled="isNotAllowed || !enabled"
                  v-bind="attrDragOptions"
                  handle=".layer-eyes"
                  :empty-insert-threshold="500"
                  @start="enabled = true"
                  @end="dragEnd"
                >
                  <!-- 关系数据在处理时增加了item.key -->
                  <transition-group
                    type="transition"
                    :name="!enabled ? 'flip-list' : null"
                  >
                    <div
                      v-for="(option, num) in item.children"
                      :key="`option-${num}`"
                      @drop.prevent.stop
                    >
                      <div
                        v-if="!(isNotAllowed && !option.visible)"
                        class="item-option"
                      >
                        <div
                          v-if="option.target"
                          class="option-content"
                          :class="{ hide: !option.visible }"
                          @contextmenu="
                            (event) =>
                              onContextMenu(event, item._id_, option._id_)
                          "
                        >
                          <div class="content-key" :style="contentKeyStyle">
                            <span class="name" :style="contentKeyStyle">{{
                              option.attrName
                            }}</span>
                          </div>
                          <div
                            class="entity-link"
                            @click.stop="
                              openOtherEntityPanel(
                                option.target,
                                option.attrValue
                              )
                            "
                          >
                            <span>{{ option.attrValue }}</span>
                          </div>
                        </div>
                        <div
                          v-else-if="['link', 'email'].includes(option.type)"
                          class="option-content"
                          :class="{ hide: !option.visible }"
                          @contextmenu="
                            (event) =>
                              onContextMenu(event, item._id_, option._id_)
                          "
                        >
                          <div class="content-key" :style="contentKeyStyle">
                            <span class="name" :style="contentKeyStyle">{{
                              option.attrName
                            }}</span>
                          </div>
                          <a
                            class="entity-link"
                            :href="
                              option.type === 'email'
                                ? `mailto:${option.attrValue}`
                                : option.attrValue
                            "
                            :title="option.attrValue"
                            target="_blank"
                          >
                            {{ option.attrValue }}
                          </a>
                        </div>
                        <div
                          v-else
                          class="option-content"
                          :class="{ hide: !option.visible }"
                          @contextmenu="
                            (event) =>
                              onContextMenu(event, item._id_, option._id_)
                          "
                        >
                          <div class="content-key" :style="contentKeyStyle">
                            <span class="name" :style="contentKeyStyle">
                              <span
                                v-if="option.type === 'table'"
                                style="margin-right: 2px;"
                              >
                                <a-icon-font type="iconshujubiao" />
                              </span>
                              <span
                                v-if="option.type === 'chart'"
                                style="margin-right: 2px;"
                              >
                                <a-icon-font type="iconzhexiantu1" />
                              </span>
                              <span> {{ option.attrName }} </span>
                            </span>
                          </div>
                          <div
                            v-if="
                              !['graph', 'table', 'chart', 'img'].includes(
                                option.type
                              )
                            "
                            class="content-value wrapper"
                            :class="{
                              'hide-btn':
                                option.attrValue.length < 30 ||
                                option.attrValue.includes('http'),
                            }"
                          >
                            <input
                              :id="`${entityData.id}_${option._id_}`"
                              class="exp"
                              type="checkbox"
                            />
                            <div class="text">
                              <label
                                class="btn"
                                :for="`${entityData.id}_${option._id_}`"
                              ></label>
                              <span
                                class="content-value"
                                v-html="option.attrValue"
                              ></span>
                            </div>
                          </div>
                        </div>
                        <div class="icon-list">
                          <!-- 常驻icon -->
                          <div
                            v-if="option.type === 'gis'"
                            class="icon-style"
                            :class="{
                              'btn-select': checkIfLayerStucked(option.layerId),
                            }"
                            @click.stop="toggleStuckInMap(option.layerId)"
                          >
                            <a-icon-font type="icona-gudingdaoGISbeifen3" />
                          </div>
                          <!-- chart edite icon -->
                          <div
                            v-if="option.type === 'chart' && !isNotAllowed"
                            class="edit-icon icon-style"
                            @click.stop="openChartConfig(option)"
                          >
                            <a-icon-font type="iconicon-beifen6-copy-copy" />
                          </div>
                          <!-- zoom in to view -->
                          <div
                            v-if="
                              option.visible &&
                              ['chart', 'table', 'graph', 'img'].includes(
                                option.type
                              )
                            "
                            class="icon-style"
                            @click.stop="openView(option)"
                          >
                            <a-tooltip placement="top">
                              <template slot="title">
                                <span>放大查看</span>
                              </template>
                              <a-icon-font
                                type="iconfangdahuabanquanping"
                              ></a-icon-font>
                            </a-tooltip>
                          </div>
                          <!-- eyes -->
                          <div
                            v-if="!isNotAllowed"
                            class="layer-eyes icon-style"
                            @click.stop="
                              optionToggleShow(item._id_, option._id_)
                            "
                            @mouseenter="mouseenter()"
                            @mouseleave="mouseleave()"
                          >
                            <a-icon-font
                              :type="
                                option.visible
                                  ? hovering
                                    ? 'icona-chakanbeifen21'
                                    : 'icona-chakanbeifen2'
                                  : hovering
                                  ? 'icona-chakanbeifen19'
                                  : 'icona-chakanbeifen14'
                              "
                            />
                          </div>
                        </div>
                      </div>
                      <!-- <div
                        v-if="option.type === 'img' && option.visible"
                        class="media-container"
                      >
                        <img
                          :src="option.attrValue"
                          alt="pic"
                          class="option-media"
                        />
                      </div> -->
                      <!-- <div
                        v-if="option.type === 'graph' && option.visible"
                        class="media-container"
                        @click.stop
                      >
                        <simple-k-graph-vis
                          :raw-data="option.attrValue"
                          :query-select-id="`graph${Math.random()
                            .toString(36)
                            .slice(-8)}`"
                          :container-width="panelWidth"
                          @on-node-select-change="handleNodeClick"
                        />
                      </div> -->
                      <div
                        v-if="
                          option.visible &&
                          ['chart', 'table', 'graph', 'img'].includes(
                            option.type
                          )
                        "
                        class="media-container"
                      >
                        <div
                          v-if="targetGridAttr(option, 'isLoading')"
                          class="loading-mask"
                        >
                          <div class="loading-status">
                            <a-icon class="sync-icon" type="sync" spin /><span
                              class="loading-text"
                              >加载中...</span
                            >
                          </div>
                        </div>
                        <template>
                          <pageTableVue
                            v-if="option.type === 'table'"
                            :is-sortable="true"
                            :page-disabled="false"
                            :config="targetGrid(option)"
                            class="option-media"
                            @pagechange="
                              (pageConfig) =>
                                onTablePageChange(
                                  targetGrid(option),
                                  pageConfig
                                )
                            "
                            @sortchange="
                              (sortData) => {
                                onTableSortchange(targetGrid(option), sortData)
                              }
                            "
                          >
                          </pageTableVue>
                          <template v-else-if="option.type === 'chart'">
                            <Chart
                              v-if="option.widgetId"
                              class="chart-design"
                              :config="targetGridAttr(option, 'chartOptions')"
                              :chart-type="targetGridAttr(option, 'chartType')"
                              @chartinit="
                                (instance) => {
                                  onChartInstanceInit(instance, option)
                                }
                              "
                              @chartevent="
                                (data) => {
                                  onChartEvent(data, option)
                                }
                              "
                            >
                            </Chart>
                          </template>
                          <template v-else-if="option.type === 'graph'">
                            <simple-k-graph-vis
                              :id="entityData.id"
                              :raw-data="option.attrValue"
                              :query-select-id="`graph${Math.random()
                                .toString(36)
                                .slice(-8)}`"
                              :container-width="panelWidth"
                              @on-node-select-change="handleNodeClick"
                            />
                          </template>
                          <template v-else>
                            <img
                              :src="option.attrValue"
                              alt="pic"
                              class="option-media"
                            />
                          </template>
                        </template>
                      </div>
                    </div>
                  </transition-group>
                </draggable>
              </div>

              <div class="split-line"></div>
            </div>
          </div>
        </transition-group>
      </draggable>
    </div>
    <div
      v-show="contextmenuVisible && !isNotAllowed"
      ref="contextmenuDropdown"
      class="contextmenu-box"
      :style="{
        left: `${contextmenuStyle.left}px`,
        top: `${contextmenuStyle.top}px`,
      }"
    >
      <ul class="ant-kg-appl-dropdown-menu">
        <li class="ant-kg-appl-dropdown-menu-item" @click="onOpenMoveToBox">
          移动到...
        </li>
      </ul>
    </div>
    <!-- 移动到... box -->
    <a-modal
      v-model="moveToModalVisible"
      :width="360"
      centered
      title="移动到..."
      cancel-text="取消"
      ok-text="确定"
      @ok="confirmMoveTo"
      @cancel="cancelMoveTo"
    >
      <div class="target-box">
        <div class="target-text">目标抽屉:</div>
        <a-select
          v-model="targetDrawer"
          :max-tag-text-length="70"
          :allow-clear="true"
          class="target-select"
        >
          <a-select-option
            v-for="(item, index) in drawerList"
            :key="index"
            :value="item.id"
          >
            {{ item.name }}
          </a-select-option>
        </a-select>
      </div>
      <div class="place-posiiton-box">
        <div class="target-text">放置位置:</div>
        <div style="position: relative;">
          <div class="up-down">
            <span class="func-link" @click.stop="placePosition('up')">
              置顶
            </span>
            <span class="func-link" @click.stop="placePosition('down')">
              置底
            </span>
          </div>
          <div class="option-list">
            <template v-if="targetDrawer">
              <div v-if="targetOptions.length > 0" class="search-options">
                <div
                  class="line-box"
                  :class="{ 'show-locate': locateIndex === 0 }"
                  style="margin-left: 28px;"
                >
                  <a-icon type="caret-right" class="arrow-icon" />
                  <div class="locate-line" @click="locateIndex = 0"></div>
                </div>

                <div
                  v-for="(option, index) in targetOptions"
                  :key="index"
                  class="option"
                >
                  <span style="display: inline-block; margin-bottom: 5px;">{{
                    option.attrName
                  }}</span>
                  <div
                    class="line-box"
                    :class="{ 'show-locate': locateIndex === index + 1 }"
                  >
                    <a-icon type="caret-right" class="arrow-icon" />
                    <div
                      class="locate-line"
                      @click="locateIndex = index + 1"
                    ></div>
                  </div>
                </div>
              </div>
              <div v-else class="empty-text">无</div>
            </template>
          </div>
        </div>
      </div>
    </a-modal>
    <view-modal
      :id="entityData.id"
      :visible="isViewModalVisible"
      :config="viewOption.config"
      :type="viewOption.type"
      :title="viewOption.title"
      @ok="closeView"
    >
    </view-modal>
  </div>
  <!-- </div> -->
</template>

<script lang="ts">
/**
 * 搜索地图
 */
import { Component, Watch, Vue, Prop } from 'vue-property-decorator'
import KGraphStore from '@/store/modules/k-graph'
import Draggabilly from 'draggabilly'
import draggable from 'vuedraggable'
import { Modal } from 'ant-design-vue'
import checkEditName from '@/util/check-util'
import { getWidgetData } from '@/api/widget'
import {
  parseGetDataResult,
  parseChartType,
} from '@/components/common/VisualizationDashboard/util'
import { cloneDeep, debounce, isEqual } from 'lodash'
// import { enableConvertToCoor } from '@/util/recommend-visualization'
import { bindChartData } from '@/util/common'
import { GEOMAP_NAME } from '@/config/contant'
import pageTableVue from '@/components/pageTable/pageTable.vue'
import Chart from '@/components/chart/chart.vue'
import SimpleKGraphVis from '@/components/knowledge-vis/SimpleKGraphVis.vue'
import elementResizeDetectorMaker from 'element-resize-detector'
// import DataViewStore from '@/store/modules/dataview'
import viewModal from '@/components/knowledge-gis/viewModal.vue'
import slidePosition from '@/components/knowledge-gis/slidePosition.vue'

@Component({
  components: {
    draggable,
    pageTableVue,
    Chart,
    SimpleKGraphVis,
    viewModal,
    slidePosition,
  },
  directives: {
    focus: {
      inserted: (element: any) => {
        element.focus()
      },
    },
  },
})
export default class KEntityPanel extends Vue {
  // @Prop({ type: Boolean, default: false }) visible!: boolean
  @Prop() sourceData!: any
  @Prop() relation!: any

  public entityData: any = {}
  public drawerList: any = []
  public drag: any = null
  // private hoverItemId: number = -1
  public expandedKeys: any = []
  public enabled: boolean = true // 拖拽禁用
  public editName: string | null = null //  新抽屉命名
  private activeEditItemName: string = '' // 编辑的 item name
  public panelWidth: number | null = null
  public panelHeight: number | null = null
  public panelTop: number | null = null
  public panelRight: number | null = null
  public panelLeft: number | null = null //  为了应对在开始阶段能够调整宽高

  private selfPanelRightPos: number = 0 //  面板向右偏移量
  private contextmenuVisible: boolean = false // 右键菜单是否展示

  private currentOptionId: number = 0 //  当前要移动的option _id_
  private currentItemId: number = 0 //  当前要移动的option所属的 _id_
  private contextmenuStyle: { top: number; left: number } = { top: 0, left: 0 } // 右键菜单样式
  public moveToModalVisible: boolean = false //  是否显示moveTo modal

  public targetDrawer: string = '' //  目标抽屉item _id_
  public locateIndex: number = 0 //  放置位置序号

  public get publishNo() {
    return KGraphStore.publishNo || undefined
  }

  public get focusBox() {
    return KGraphStore.focusBox
  }

  // 项目锁定
  public get isLock() {
    // return DataViewStore.getLock
    return false
  }

  public isViewModalVisible: boolean = false
  public viewOption: any = {}
  public hovering: boolean = false

  mouseenter() {
    this.hovering = true
  }
  mouseleave() {
    this.hovering = false
  }

  /**
   * 点击放大查看图表
   * type: table | chart
   */
  public openView(option: any) {
    this.isViewModalVisible = true
    let config: any = null
    let type: String = ''
    switch (option.type) {
      case 'chart':
        config = this.targetGrid(option)
        type = this.targetGridAttr(option, 'chartType')
        break
      case 'table':
        config = this.targetGrid(option)
        type = option.type
        break
      case 'graph':
      case 'img':
        config = option
        type = option.type
        break
      default:
        break
    }
    this.viewOption = {
      config,
      type,
      title: option.attrName,
    }
  }

  public closeView() {
    this.isViewModalVisible = false
  }
  /**
   * 确认执行 move to
   */
  public confirmMoveTo() {
    let moveOption: any
    //  移除option 在原item下
    // eslint-disable-next-line no-restricted-syntax
    for (const item of this.entityData.items) {
      if (item._id_ === this.currentItemId) {
        const index = item.children.findIndex((option: any) => {
          return option._id_ === this.currentOptionId
        })
        moveOption = item.children.splice(index, 1)
      }
    }

    //  添加option 在现item下
    // eslint-disable-next-line no-restricted-syntax
    for (const item of this.entityData.items) {
      if (item._id_ === this.targetDrawer) {
        item.children.splice(this.locateIndex, 0, moveOption[0])
      }
    }

    //  清空选项
    this.targetDrawer = ''
    this.currentOptionId = 0

    this.moveToModalVisible = false
  }
  /**
   * 取消执行 move to
   */
  public cancelMoveTo() {
    this.targetDrawer = ''
    this.currentOptionId = 0
  }

  public getDrawerList() {
    const result: Array<object> = []
    this.entityData.items?.forEach((item: any) => {
      result.push({
        name: item.name,
        id: item._id_,
      })
    })
    return result
  }

  public get targetOptions() {
    const target = this.entityData.items.find((item: any) => {
      return item._id_ === this.targetDrawer
    })
    return target.children.filter((option: any) => {
      return option._id_ !== this.currentOptionId
    })
  }

  /**
   * 放置位置 move to
   * @param posiiton 放置的位置 - up / down
   */
  public placePosition(posiiton: string) {
    if (posiiton === 'up') {
      this.locateIndex = 0
    } else {
      this.locateIndex = this.targetOptions.length
    }
  }

  /**
   * 右键菜单 move to
   * @param event
   * @param itemId  当前要移动option 所属的 item id
   * @param optionId  当前要移动option id
   */
  private onContextMenu(event: any, itemId: number, optionId: number) {
    event.preventDefault()

    this.contextmenuVisible = true
    this.currentOptionId = optionId
    this.currentItemId = itemId

    this.contextmenuStyle = {
      top: event.layerY,
      left: event.layerX,
    }
  }

  public onOpenMoveToBox() {
    this.moveToModalVisible = true
  }

  mounted() {
    const that = this
    this.selfPanelRightPos = this.panelRightPos

    // if (!this.isNotAllowed) {
    setTimeout(() => {
      const $overlay = document.querySelector(
        this.fromPreviewPublish
          ? 'preview-gis-map-component'
          : '.gis-map-component'
      ) as HTMLDivElement
      const $element = document.querySelector(
        `#entity-${this.entityData.id}`
      ) as HTMLDivElement
      that.drag = new Draggabilly($element, {
        containment: $overlay,
        handle: '.header',
        grid: [1, 1],
      })

      that.drag.on('dragEnd', () => {
        if (!that.isNotAllowed) {
          const parent = document.querySelector(
            '.gis-map-component'
          ) as HTMLElement
          const result =
            parent?.clientWidth - that.drag.position.x - $element.clientWidth
          console.log(that.drag.position, 'result', result)

          that.panelRight = result
          that.panelTop = that.drag.position.y
          that.panelLeft = that.drag.position.x

          // $element.style.height = '480px'
        }
        // if (!$element.classList.contains('resize-tag')) {
        //   $element.classList.add('resize-tag')
        //   $element.style.height = '480px'
        // }
      })
    }, 500)

    // }
    // 改为实时监听模式，避免表格高度不同步的情况
    this.$nextTick(() => {
      const erdTable = elementResizeDetectorMaker()
      const auditTable = document.querySelector(
        `#entity-${this.entityData.id}`
      ) as HTMLDivElement
      erdTable.listenTo(auditTable, (element: HTMLElement) => {
        that.changePanelsize(element.clientHeight, element.clientWidth)
      })
      this.$once('hook:beforeDestroy', () => {
        erdTable.removeAllListeners(auditTable)
      })
    })
  }

  public changePanelsize = debounce((height: number, width: number) => {
    this._changePanelsize(height, width)
  }, 500)

  public _changePanelsize(height: number, width: number) {
    this.panelWidth = width
    this.panelHeight = height
    this.resizedAllItems()
  }

  updateChartSize(item: any, index: number) {
    const isNotChart = ['table'].includes(item.type)

    if (isNotChart) {
      return
    }

    const width: any = this.panelWidth

    // 更改chart size
    item.chartOptions.size = [width - 50, 220]

    Vue.set(this.gridList, index, item)
  }

  // 调整当前面板chart 大小
  public resizedAllItems() {
    this.gridList.forEach((gridItem: any, index: any) => {
      this.updateChartSize(gridItem, index)
    })
  }
  //   处理点击关系图里的node
  public handleNodeClick(dataInfo: any) {
    const { id, label } = dataInfo
    //  不会重复打开自己的实体面板
    if (this.entityData.id !== Number(id)) {
      this.openOtherEntityPanel(id, label)
    }
  }
  //  附上id name -> 为了应对面数据 实体
  public openOtherEntityPanel(id: number, entityName: string) {
    this.$emit('open-entity', {
      id,
      searchKey: entityName,
    })

    //  如果原本存在位置信息 或者 当前panel 移动有了位置信息，则不需要增加系统指定的右偏移
    if (!('position' in this.entityData || this.panelRight)) {
      KGraphStore.setEntityPanelRightPos(
        cloneDeep(this.panelRightPos) + 300 + 16
      )
    }
  }

  public resetInitWidth() {
    const panel: any = document.querySelector(
      '.entity-container'
    ) as HTMLElement
    panel.style.width = '300px'
    this.panelWidth = 300
  }

  //  置顶当前实体面板
  public UpEntityPanel(id: number) {
    //  store save
    KGraphStore.setSelectEntityPanel(id)

    this.contextmenuVisible = false

    //  set focus box
    KGraphStore.setFocusBoxg('entity')
  }
  //  获取当前置顶的面板id
  public get selectEntityPanel() {
    return KGraphStore.selectEntityPanel
  }

  public get panelRightPos() {
    return KGraphStore.entityPanelRightPos
  }

  public containerStyle() {
    const result = this.selfPanelRightPos
    //  fix enitty panel init resize issue for preview/publish mode,
    const map = document.querySelector(
      '.preview-gis-map-component'
    ) as HTMLElement
    const {
      width = '300px',
      height = '98%',
      position = { top: '0', right: `${result}px`, left: 'auto' },
    } = this.entityData
    const widthShape = !width ? '300px' : width
    const heightShape = !height ? '98%' : height
    return {
      width: widthShape,
      height: heightShape,
      left: this.fromPreviewPublish
        ? `${
            map.clientWidth -
            Number(widthShape.slice(0, widthShape.indexOf('px'))) -
            Number(position.right.slice(0, position.right.indexOf('px')))
          }px`
        : position.left,
      right: position.right,
      top: position.top,
    }
  }

  public get knowledgeGraphMode(): string {
    return KGraphStore.knowledgeGraphMode
  }

  get isNotAllowed() {
    return this.isPreview || this.isPublish || this.isLock
  }

  get fromPreviewPublish() {
    return this.isPreview || this.isPublish
  }

  get isPreview() {
    return this.knowledgeGraphMode === 'preview'
  }

  get isPublish() {
    return this.knowledgeGraphMode === 'publish'
  }

  get gridList() {
    const target = KGraphStore.gridList.find(
      (item: any) => item.id === this.entityData.id
    )
    return target?.list ?? []
  }

  public get targetGrid() {
    return (option: any) => {
      return this.gridList.find((item: any) => item._id_ === option._id_)
    }
  }

  // 根据面板宽度，动态调整属性列所占的宽度
  public get contentKeyStyle() {
    return {
      width:
        this.panelWidth === null || this.panelWidth <= 320 ? '80px' : '120px',
    }
  }

  public targetGridAttr(option: any, name: string) {
    const target = this.gridList.find((item: any) => item._id_ === option._id_)

    if (name === 'chartType') {
      return parseChartType(target.chartType || '')
    }
    return target ? target[name] : false
  }

  public get entityList() {
    return KGraphStore.entityLayer
  }

  // ========> For Chart event
  onChartInstanceInit(chartInstance: any, item: any) {
    console.log(chartInstance, item)
    // this.dataStore.setChartInstanceMaps({
    //   instance: chartInstance,
    //   key: item.i,
    // })
  }

  public onChartEvent = debounce((data: any, option: any) => {
    this._onChartEvent(data, option)
  }, 300)

  /**
   * chart触发的事件
   */
  private _onChartEvent(data: any, option: any) {
    const item = this.targetGrid(option)
    let clickedName: any
    switch (data.name) {
      case 'selectedChange':
      case 'graphNodeClick': // graph node 点击
        // const clickedName = data.event.data.data[item.chartOptions.labelKey]
        console.log(
          data.event.data.data[item.chartOptions.labelKey],
          'okokok',
          item
        )
        clickedName = data.event.data.data[item.chartOptions.labelKey]
        //  只允许有一个选中的维度
        if (this.selectedDimension.includes(clickedName)) {
          this.selectedDimension.pop()
        } else if (item.interactActive.turnOn) {
          //  未点击且开启了交互属性
          //  request BE api with value, then get entity id or 前端实现搜索查询
          const entity = this.entityList.find((target: any) => {
            return target.name === clickedName
          })
          this.openOtherEntityPanel(entity.entityId, clickedName)
          this.selectedDimension.push(clickedName)
        }

        break
      default:
        break
    }
  }
  //  图表选中的维度记录
  public selectedDimension: string[] = []

  public get dragOptions() {
    return {
      animation: 200,
      group: 'description',
      disabled: false,
      ghostClass: 'ghost',
    }
  }

  public get attrDragOptions() {
    return {
      animation: 200,
      group: 'attr',
      disabled: false,
      ghostClass: 'ghost',
    }
  }

  public dragEnd() {}

  public initExpandTab() {
    this.expandedKeys = []
    // eslint-disable-next-line no-restricted-syntax
    for (const item of this.entityData.items) {
      if (!item.fold) {
        this.expandedKeys.push(item._id_)
      }
    }
  }
  //  初始化grid list
  public initGridList() {
    const gridList = []
    // eslint-disable-next-line no-restricted-syntax
    for (const item of this.entityData.items) {
      // eslint-disable-next-line no-restricted-syntax
      for (const option of item.children) {
        const copyOption = cloneDeep(option)
        copyOption.isLoading = false
        if (option.type === 'chart') {
          //  在发布态，需要从config_publish 拿 config 信息
          const config = JSON.parse(
            this.isPublish ? copyOption.config_publish : copyOption.config
          )

          //  除table 之外的chart
          // if (option.chartType !== 'table') {
          // const { config } = copyOption
          // const config = JSON.parse(copyOption.config)
          //  config 要JSON.parse
          copyOption.dataQuery = {
            data: {
              id: config.chartOptions.dataId,
              type: config.chartOptions.dataType,
              widgetJson: config.widgetJson,
            },
          }
          copyOption.chartOptions = config.chartOptions
          copyOption.chartType = config.chartType
          copyOption.interactActive = config?.interactActive ?? {
            turnOn: false,
          }
          // }

          gridList.push(copyOption)
        } else if (option.type === 'table') {
          gridList.push(copyOption)
        }
      }
    }

    KGraphStore.addGridList({
      id: this.entityData.id,
      list: gridList,
    })
    // this.$nextTick(() => {
    this.initWidget()
    // })
  }
  //  初始化widget
  public initWidget() {
    if (this.gridList.length > 0) {
      this.gridList.forEach((gridItem: any) => {
        // parseChartOptionToFunction(gridItem.chartOptions)
        // if (gridItem.widgetId && gridItem.chartOptions) {
        this.getWidgetData(gridItem)
        // }
      })
    }
  }

  /** 判断gridItem是否为地图组件 */
  gridItemIsGeoMap(gridItem: any) {
    return (gridItem.chartType as Array<string>).includes(GEOMAP_NAME)
  }

  //  后续可以添加根据visible 情况 获取widget
  public getWidgetData(gridItem: any) {
    if (gridItem.type === 'table') {
      this.getTableData(gridItem)
    } else {
      //  chart ....
      const query = {
        data: gridItem.dataQuery?.data,
      }

      query.data.tableName = query.data.id
      // query.data.id = undefined
      // if (this.forAllVisitors) {
      query.data.publishNo = this.publishNo
      // }

      //  暂无地理信息
      // if (enableConvertToCoor(gridItem.chartOptions)) {
      //   // 需要映射地理数据（省份、城市、ip等映射成经纬度）
      //   query.data.convert = gridItem.chartOptions.geoTransform.fields
      // }
      this.$set(gridItem, 'isLoading', true)

      //  TODO: query 需要变化

      getWidgetData(query)
        .then((response) => {
          if ([100, 1106].includes(response.data.code)) {
            const chartType = Array.isArray(gridItem.chartType)
              ? gridItem.chartType[1]
              : gridItem.chartType
            const index = this.getGridIndex(
              this.gridList,
              gridItem._id_ as string
            )

            this.gridItemSyncBindData({
              data: {
                query,
                data: parseGetDataResult(
                  response.data?.result || {
                    columns: [],
                    data: [],
                    extraData: {},
                  },
                  chartType,
                  gridItem
                ),
                columns: gridItem.columns,
              },
              gridItem,
              index,
            })
            this.$set(gridItem, 'isLoading', false)
          } else {
            this.$message.error(response.data.message)
          }
        })
        .catch(() => {
          this.$set(gridItem, 'isLoading', false)
        })
    }
  }

  gridItemSyncBindData(parameterSet: any) {
    const { data, gridItem, index } = parameterSet
    const gridItemSet: any | null = bindChartData(gridItem, data)
    if (gridItemSet) {
      if (this.panelWidth) {
        const width: any = this.panelWidth
        // 更改chart size
        gridItemSet.chartOptions.size = [width - 50, 220]
      } else {
        // 设置默认的 chart size
        gridItemSet.chartOptions.size = [250, 220]
      }

      setTimeout(() => {
        this.$set(gridItemSet, 'isLoading', false)
      }, 100)
      Vue.set(this.gridList, index, gridItemSet)
    }
  }

  // ========> For TablePage
  onTablePageChange(
    gridItem: any,
    pageConfig: { pageNumber: number; pageSize: number }
  ) {
    this.$set(gridItem.chartOptions, 'curPage', pageConfig.pageNumber)
    this.$set(gridItem.chartOptions, 'pageSize', pageConfig.pageSize)
    this.getTableData(gridItem)
  }

  /**
   * 排序
   */
  private onTableSortchange(
    gridItem: any,
    sortData: { key: string; sort: 'desc' | 'asc' }
  ) {
    if (sortData.key) {
      this.$set(gridItem.chartOptions, 'sortCol', [
        { name: sortData.key, sort: sortData.sort },
      ])
      this.getTableData(gridItem)
    }
  }

  //  获取table data
  getTableData(gridItem: any) {
    if (gridItem && gridItem.type === 'table') {
      const dataSend: any = {
        data: {
          publishNo: this.publishNo,
          tableName: gridItem.attrValue, //  replace attr id with tableName
          type: 'dataset',
          tableJson: {
            curPage: gridItem.chartOptions?.curPage ?? 1,
            pageSize: gridItem.chartOptions?.pageSize ?? 50,
            name: '_record_id_',
            filters: [],
            sortCol: gridItem.chartOptions?.sortCol ?? [],
          },
        },
      }

      this.$set(gridItem, 'isLoading', true)
      // dataSend 需要变化 TODO
      getWidgetData(dataSend)
        .then((response: any) => {
          if ([100, 1106].includes(response.data.code)) {
            const gridItemClone = cloneDeep(gridItem)
            const { chartOptions } = gridItemClone

            KGraphStore.updateGridListItem({
              ...gridItemClone,
              isLoading: false,
              chartOptions: {
                ...chartOptions,

                columns: response.data.result.columns.map((column: any) => {
                  return column.name
                }),
                curPage: response.data.result?.page?.curPage || 0,
                totalElements: response.data.result?.page?.totalElements || 0,
                pageSize: response.data.result?.page?.pageSize || 50,
                value: response.data.result
                  ? parseGetDataResult(response.data.result)
                  : [],
                totalPages: response.data.result?.page?.totalPages,
              },
              entityId: this.entityData.id,
            })

            this.$set(gridItem, 'isLoading', false)
          } else {
            this.$message.error(response.data.message)
          }
        })
        .catch(() => {
          this.$set(gridItem, 'isLoading', false)
        })
    } else {
      console.error('call error: getTableData must be used by table')
    }
  }

  /** 获取gridIndex */
  getGridIndex(parent: any, id: string) {
    return parent.findIndex((item: any) => item._id_ === id)
  }

  public clickItem(event: Event, item: any) {
    console.log(event, item)
  }

  /**
   * 双击实体抽屉修改名称
   * @param item
   */
  public editItemName(item: any) {
    if (this.isNotAllowed) {
      return
    }
    if (item.editable) {
      this.editName = item.name
      this.activeEditItemName = item.name
      this.enabled = false
    }
  }

  public setItemName(target: any, newName: string) {
    // eslint-disable-next-line no-restricted-syntax
    for (const item of this.entityData.items) {
      if (item._id_ === target._id_) {
        item.name = newName
      }
    }
  }

  /**
   * 修改实体抽屉名称校验
   * 1-正常， 2-全空字符串， 3-重名， 5-和原名相同， 4-空
   */
  public editLayerNameCheck($event: any, item: any) {
    const flag: string = checkEditName(
      item,
      this.entityData.items,
      '_id_',
      'name',
      this.activeEditItemName
    )
    switch (flag) {
      case 'pass':
        this.enabled = true
        this.setItemName(item, this.activeEditItemName)

        this.closeEditState()
        break
      case 'space':
        this.$message.warn('名称不能全为空格')
        this.activeEditItemName = item.name
        $event.target.focus()
        break
      case 'repetition':
        this.$message.warn('该名称已存在')
        $event.target.focus()
        break
      case 'empty':
        this.$message.warn('名称不能为空')
        this.activeEditItemName = item.name
        $event.target.focus()
        break
      case 'no-change':
        this.enabled = true
        this.closeEditState()
        break
      default:
        break
    }
  }

  public closeEditState() {
    this.editName = null
    this.activeEditItemName = ''
  }

  public toggleFold(id: string) {
    if (this.expandedKeys.includes(id)) {
      const index = this.expandedKeys.indexOf(id)
      this.expandedKeys.splice(index, 1)
    } else {
      this.expandedKeys.push(id)
    }

    //  TODO 在最后保存的时候去做fold 的重置，根据expandedKeys清空
  }

  public itemToggleShow(id: string) {
    // eslint-disable-next-line no-restricted-syntax
    for (const item of this.entityData.items) {
      if (item._id_ === id) {
        item.visible = !item.visible
        if (!item.visible) {
          // item.fold = false
          //  设置隐藏后，自动收起
          if (this.expandedKeys.includes(id)) {
            const index = this.expandedKeys.indexOf(id)
            this.expandedKeys.splice(index, 1)
          }
        }
        break

        //  为后代都设置相同的visible TBD
      }
    }
  }

  public optionToggleShow(itemId: string, optionId: string) {
    // eslint-disable-next-line no-restricted-syntax
    for (const item of this.entityData.items) {
      if (item._id_ === itemId) {
        // eslint-disable-next-line no-restricted-syntax
        for (const option of item.children) {
          if (option._id_ === optionId) {
            option.visible = !option.visible
            break
          }
        }
      }
    }
  }

  public get fixedLayerId() {
    return KGraphStore.fixedLayerId
  }

  public checkIfLayerStucked(layerId: number) {
    return this.fixedLayerId.includes(layerId)
  }

  public toggleStuckInMap(layerId: any) {
    if (this.checkIfLayerStucked(layerId)) {
      KGraphStore.deleteFixedLayerId(layerId)
    } else {
      KGraphStore.addFixedLayerId(layerId)
    }
  }
  public shapeData(entityData: any, relation: any) {
    const { items } = cloneDeep(entityData)
    // 处理关系数据
    const relationItems = items.find((item: any) => item.name === '关系')
    if (relationItems && relationItems.children.length > 0) {
      let index = items.findIndex((item: any) => item.name === '关系')
      const keys = Object.keys(relation)
      const { children, ...rest } = relationItems
      keys.forEach((key: any) => {
        const newItems = { ...rest, key, name: key, children: [] }
        children.forEach((child: any) => {
          const { attrName } = child
          if (relation[key].includes(attrName)) {
            if (key === '_first_layer_') {
              newItems.name = attrName
            }
            newItems.children.push(child)
          }
        })
        if (newItems.children?.length) {
          items.splice(index, 0, newItems)
          index += 1
        }
      })
    }
    const filterItems = items.filter((item: any) => item.name !== '关系')
    return filterItems
  }
  @Watch('sourceData', { immediate: true, deep: true })
  private watchVisible(value: any) {
    if (value) {
      this.entityData = cloneDeep(value)
      this.drawerList = this.getDrawerList()
      if (this.entityData.width) {
        this.panelWidth = Number(
          this.entityData.width.slice(0, this.entityData.width.indexOf('px'))
        )
      } else {
        this.panelWidth = 300
      }

      //  常驻图层, 当打开实体面板需要暂时显示
      this.toggleFixedLineLayer('show')

      //  TODO 为没有id 的 item 生成id ，已有则忽略；
      // const id = `item${Math.random().toString(36).slice(-8)}`

      //  TODO 初始化的时候，获取gridList 列表，type 为chart ，只负责获取画图的数据，
      //  更改还是走widget update / 顺序，显隐还是走entity data update
      this.initExpandTab()
      this.initGridList()
    } else {
      // KGraphStore.setGridList([])
      this.expandedKeys = []
    }
  }
  //  显隐 常驻图层
  public toggleFixedLineLayer(type: string) {
    // eslint-disable-next-line no-restricted-syntax
    for (const item of this.entityData.items) {
      // eslint-disable-next-line no-restricted-syntax
      for (const option of item.children) {
        //  为gis type ，并且还没有设置常驻
        if (
          option.type === 'gis' &&
          !this.checkIfLayerStucked(option.layerId)
        ) {
          if (type === 'show' && option.visible) {
            this.$emit('show-fixed', option.layerId)
          } else if (type === 'hide') {
            this.$emit('hide-fixed', option.layerId)
          }
        }
      }
    }
  }

  public removePostionData() {
    this.panelLeft = null
    this.panelRight = null
    this.panelTop = null
    this.panelWidth = null
    this.panelHeight = null
  }

  public closeEntity() {
    if (this.panelRight) {
      this.entityData = {
        ...this.entityData,
        position: {
          top: `${this.panelTop}px`,
          right: `${this.panelRight}px`,
          left: `${this.panelLeft}px`,
        },
      }
    }
    if (this.panelWidth) {
      this.entityData = {
        ...this.entityData,
        width: `${this.panelWidth}px`,
        height: `${this.panelHeight}px`,
      }
    }
    //  当该常驻图层未在图层中常驻，关闭实体面板需要移除该图层【包括箭头】
    this.toggleFixedLineLayer('hide')

    if (!('position' in this.entityData) && this.panelRightPos !== 0) {
      KGraphStore.setEntityPanelRightPos(
        cloneDeep(this.panelRightPos) - 300 - 16
      )
    }

    this.assignFoldKey()
    //  当实体信息有变更 且 处在编辑态
    if (!isEqual(this.entityData, this.sourceData) && !this.isNotAllowed) {
      //  监测到实体数据变化，弹出确认窗口
      const that = this
      Modal.confirm({
        title: '是否保存实体面板信息？',
        content: '检测到实体面板信息发生了变更，是否保存？',
        okText: '确定',
        cancelText: '取消',
        onOk() {
          that.$emit('close-entity', {
            entityData: that.entityData,
            shouldSave: true, //  需要请求后端接口进行保存
          })
          that.expandedKeys = []
          that.removePostionData()
        },
        onCancel() {
          that.$emit('close-entity', {
            entityData: that.entityData,
            shouldSave: false,
          })
          that.expandedKeys = []
          that.removePostionData()
        },
      })
      return
    }

    this.$emit('close-entity', {
      entityData: this.entityData,
      shouldSave: false,
    })
    this.expandedKeys = []
    this.removePostionData()

    // KGraphStore remove gridList set
  }
  //  赋值展开的抽屉
  public assignFoldKey() {
    // eslint-disable-next-line no-restricted-syntax
    for (const item of this.entityData.items) {
      item.fold = !this.expandedKeys.includes(item._id_)
    }
  }

  //  实体重置
  public entityReset() {
    const that = this
    Modal.confirm({
      title: '确定要重置吗？',
      content:
        '重置后内容将恢复至初始内容，更改的内容将全部删除，是否确定继续此操作？',
      okText: '确定',
      cancelText: '取消',
      onOk() {
        that.$emit('reset-entity', that.entityData.id)
        that.removePostionData()
      },
    })
  }

  public openChartConfig(option: any) {
    const gridItem = this.targetGrid(option)

    //  如果原本存在位置信息 或者 当前panel 移动有了位置信息，则不需要增加系统指定的右偏移
    if (!('position' in this.entityData || this.panelRight)) {
      KGraphStore.setEntityPanelRightPos(
        cloneDeep(this.panelRightPos) + 300 + 16
      )
    }

    KGraphStore.setCurrentGridItem({
      ...gridItem,
      entityId: this.entityData.id,
      right: this.entityData?.position?.right ?? this.selfPanelRightPos,
    })
  }

  public addAttr() {
    // const id = `item${Math.random().toString(36).slice(-8)}`
    const id = this.entityData.next_id_
    this.entityData.next_id_ += 1
    this.entityData.items.unshift({
      name: `新建抽屉${id}`,
      // order: 3, //  可以不用
      visible: true,
      fold: false,
      editable: true,
      _id_: id,
      children: [],
    })

    this.expandedKeys.push(id)
  }

  private destroyed() {
    if (this.drag) {
      this.drag.destroy()
    }
  }
}
</script>
<style lang="less">
:root {
  --title-color: #373b52;
  --component-bg-color: #fff;
  --component-bg-color-tspt: #fff;
  --component-bg-color-oneop: #fff;
  --component-border-color: #e9e9e9;
  --controller-label: #373b52;
  --controller-input-border: #e9e9e9;
  --controller-innput-arrow: #5d637e;
  --controller-slider-rail: rgba(0, 0, 0, 0.08);
  --controller-palceholder: rgba(0, 0, 0, 0.25);
  --table-th: rgb(250, 250, 250, 0.4);
  --table-tr: rgb(255, 255, 255, 0.7);
  --table-pag-active-num: #6973ff;
  --table-pag-num: #5d637e;
  --table-row-hover: #eff0fe;
  --table-border: rgba(217, 217, 217, 0.4);
  --content-box-bg: rgba(235, 234, 239, 1);
  --tooltip-bg: rgb(255, 255, 255);
}

.target-box {
  display: flex;
  margin-bottom: 16px;

  .target-text {
    margin: auto 0;
  }

  .target-select {
    margin-left: 10px;
    width: 77%;
  }
}

.place-posiiton-box {
  display: flex;
  justify-content: space-between;

  .target-text {
    margin-top: 17px;
  }

  .up-down {
    color: #6973ff;
    font-size: 12px;
    position: absolute;
    right: 0;

    .func-link {
      cursor: pointer;
      margin-left: 8px;
    }
  }

  .option-list {
    border: 1px solid #d9d9d9;
    border-radius: 2px;
    height: 95px;
    margin-top: 17px;
    width: 240px;

    .search-options {
      height: 100%;
      overflow-y: scroll;
      padding: 10px;

      .option {
        margin: 0 8px 5px 28px;
      }
    }

    .empty-text {
      background: rgba(0, 0, 0, 0.04);
      color: #222432;
      font-size: 14px;
      margin: 15px 12px;
      opacity: 0.5;
      text-align: center;
    }

    .line-box {
      cursor: pointer;
      opacity: 0;
      position: relative;

      .arrow-icon {
        color: rgb(105, 115, 255);
        left: -15px;
        position: absolute;
        top: -6.5px;
      }

      .locate-line {
        border-top: 1px solid #6973ff;
        height: 1px;
        left: 0;
        margin: 2px 0;
        padding: 3px 0;
        width: 100%;
      }
    }

    .show-locate.line-box {
      opacity: 1;
    }
  }
}
</style>

<style scoped lang="less">
.resize-drag {
  overflow: hidden;
  resize: both;

  .header {
    cursor: grab;
  }
}

.entity-container.up-panel {
  z-index: 1000;
}

.entity-container {
  background: #fff;
  border-radius: 2px;
  box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.18);
  height: 98%;
  min-height: 200px;
  min-width: 300px;
  position: absolute;
  top: 1px;
  width: 300px;
  z-index: 700;

  .header {
    align-items: center;
    display: flex;
    justify-content: space-between;
    margin: 9px 12px;
    min-height: 32px;

    .panel-name {
      font-family: 'PingFangSC-Medium';
      letter-spacing: 1px;
      // overflow: hidden;
      // text-overflow: ellipsis;
      // white-space: nowrap;
    }

    .func-list {
      display: flex;
      flex-direction: row;

      .func-icon {
        align-items: center;
        border-radius: 2px;
        color: rgb(93, 99, 126);
        cursor: pointer;
        display: flex;
        font-size: 16px;
        padding: 4px;
        position: relative;
        user-select: none;
      }
    }
  }

  .layer-body {
    background: #f9f9fc;
    height: calc(100% - 50px);
    overflow-y: scroll;
    width: 100%;

    .unvisible {
      color: #373b52;
      opacity: 0.5;
    }

    .item-header {
      align-items: center;
      // background-color: #f9f9fc;
      display: flex;
      font-size: 14px;
      font-weight: 800;
      height: 38px;
      justify-content: space-between;
      letter-spacing: 1px;
      margin-bottom: 12px;
      padding: 8px 12px;
      user-select: none;

      .item-title {
        font-family: PingFangSC-Medium;
        letter-spacing: 1px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }

      .item-func {
        display: flex;
        flex-direction: row;

        .divider {
          background: #999;
          height: 21px;
          margin: 0 10px;
          width: 1px;
        }

        .layer-eyes {
          visibility: hidden;
        }
      }

      &:hover {
        .layer-eyes {
          visibility: visible;
        }
      }
    }

    .icon-style {
      cursor: pointer;
      margin-right: 9px;

      &:hover {
        color: #6973ff;
      }
    }

    .btn-select {
      color: #6973ff;
    }

    .item-content {
      min-height: 10px;

      .item-option {
        align-items: center;
        display: flex;
        flex-direction: row;
        height: 100%;
        justify-content: space-between;
        padding: 8px 12px;
        width: 100%;

        .option-content {
          display: flex;
          flex-direction: row;
          width: 90%;

          .content-key {
            margin-right: 8px;
            white-space: pre-line;
            width: 80px;

            .name {
              display: inline-block;
              width: 80px;
            }
          }

          .content-value {
            color: #373b52;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: pre-line;
            word-wrap: break-word;
          }
        }

        .entity-link {
          color: #6973ff;
          cursor: pointer;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: pre-line;
        }

        .icon-list {
          display: flex;
          visibility: hidden;
        }

        &:hover {
          background: #e9eafb;

          .icon-list {
            visibility: visible;
          }

          .text::after {
            box-shadow: inset calc(100px - 999vw) calc(30px - 999vw) 0 0 #e9eafb;
          }
        }
      }

      .media-container {
        display: flex;
        height: 220px;
        justify-content: center;
        margin: auto;
        margin-bottom: 10px;
        position: relative;

        .option-media {
          background: #f9f9fc;
          height: 100%;
          max-width: 90%;
        }

        .loading-mask,
        .no-data {
          align-content: center;
          align-items: center;
          background: transparent;
          display: flex;
          height: 100%;
          justify-content: center;
          position: absolute;
          text-align: center;
          transform: translateY(-40px);
          width: 100%;
          z-index: 100;

          .loading-status {
            align-content: center;
            align-items: center;
            bottom: 0;
            color: var(--title-color);
            display: flex;
            flex-flow: row nowrap;
            font-size: 12px;
            font-weight: 500;
            justify-content: center;
            left: 0;
            letter-spacing: 1px;
            line-height: 36px;
            position: absolute;
            right: 0;
            top: 0;
            vertical-align: middle;
            z-index: 1000;

            .loading-text {
              display: inline-block;
              padding-left: 4px;
            }

            .sync-icon {
              color: #5760e6;
              font-size: 24px;
            }
          }
        }
      }
    }

    .hide {
      color: #373b52;
      opacity: 0.5;
    }

    .close-fold {
      display: none;
    }

    .split-line {
      border-top: 1px solid #e9e9e9;
      height: 1px;
      left: 0;
      margin: 0;
      width: 100%;
    }
  }

  /deep/ .ant-kg-appl-tree li .ant-kg-appl-tree-switcher {
    position: absolute;
    right: 5px;
  }

  /deep/ .ant-kg-appl-tree li .ant-kg-appl-tree-node-content-wrapper {
    width: 100%;
  }

  /deep/ .ant-kg-appl-tree-title {
    display: inline-block;
    position: relative;
    width: 100%;
  }

  /deep/ .eye-icon {
    cursor: pointer;
    position: absolute;
    right: 35px;
    top: 5px;
  }

  .contextmenu-box {
    position: absolute;
    width: 110px;
    z-index: 300;
  }

  /deep/ .chart-title {
    display: none;
  }

  /deep/ .chart-wrapper {
    background: #fff;
    border-radius: 2px;
    box-shadow: 0 0 4px 0 rgba(88, 98, 230, 0.2);
  }

  // expand collapse start
  .wrapper {
    display: flex;
    width: 100%;
  }

  .text {
    line-height: 1.5;
    max-height: 7.3em;
    overflow: hidden;
    position: relative;
    text-align: justify;
    text-overflow: ellipsis;
    width: 100%;
  }

  .text::before {
    content: '';
    float: right;
    height: calc(100% - 20px);
  }

  .hide-btn .btn {
    display: none;
  }

  .hide-btn .content-value {
    overflow: hidden;
    width: 80%;
  }

  .text::after {
    box-shadow: inset calc(100px - 999vw) calc(30px - 999vw) 0 0 #f9f9fc;
    content: '';
    height: 999vw;
    margin-left: -100px;
    position: absolute;
    width: 999vw;
  }

  .btn {
    background: #6973ff;
    border-radius: 4px;
    clear: both;
    color: #fff;
    cursor: pointer;
    float: right;
    font-size: 12px;
    line-height: 13px;
    margin-left: 20px;
    padding: 0 6px;
    position: relative;
    top: 7px;
  }

  .btn::after {
    content: '展开';
  }

  .exp {
    display: none;
  }

  .exp:checked + .text {
    max-height: none;
  }

  .exp:checked + .text::after {
    visibility: hidden;
  }

  .exp:checked + .text .btn::before {
    visibility: hidden;
  }

  .exp:checked + .text .btn::after {
    content: '收起';
  }

  .btn::before {
    color: #333;
    content: '...';
    left: -5px;
    position: absolute;
    transform: translateX(-100%);
  }
  // expand collapse end
}
</style>
